﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;

namespace ArmyCreator.ViewModels
{
    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="T">Type of model to be loaded into the Loadable</typeparam>
    public abstract class ALoadable<T> : INotifyPropertyChanged where T : class , new()
    {
        public bool IsDataLoaded { get; protected set; }

        public T LoadedModel { get; private set; }

        /// <summary>
        /// Load data in model and its dependency depending on depth size
        /// </summary>
        /// <param name="model">the model</param>
        /// <param name="depth">number of depth level</param>
        public void LoadData(T model, int depth)
        {
            if (depth > 0 && model != null && !IsDataLoaded)
            {
                try
                {
                    Load(model, depth);
                    LoadedModel = model;
                    IsDataLoaded = true;
                }
                catch (Exception exception)
                {
                    throw new LoadException("Exception while loading data", exception);
                }
            }
        }

        public static C LoadData<C>(T model, int depth)
            where C : ALoadable<T>, new()
        {
            var loadable = new C();
            loadable.LoadData(model, depth);
            return loadable;
        }

        protected O GetValue<O>(string key) where O : class {
            return (O) LoadedModel.GetType().GetField(key).GetValue(LoadedModel);
        }

        protected void SetValue<O>(string key, O value) where O : class {
            LoadedModel.GetType().GetField(key).SetValue(LoadedModel, value);

            if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(key));
        }

        /// <summary>
        /// Load data into the model
        /// </summary>
        /// <param name="model"></param>
        /// <param name="depth"></param>
        protected abstract void Load(T model, int depth);

        public event PropertyChangedEventHandler PropertyChanged;
    }
}
